﻿using System;
using System.IO;
using System.Runtime.Serialization;
using System.Windows.Media.Imaging;
using SymulatorEthernetWPF.Shared;
using SymulatorEthernetWPF.UserInterface;
using SymulatorEthernetWPF.SimObjects.Layers.Physical;
using SymulatorEthernetWPF.SimObjects.Layers.DataLink;
using System.Timers;
using System.Windows;
using System.Collections.Generic;

namespace SymulatorEthernetWPF.SimObjects.Devices
{
    [Serializable]
    internal class SwitchControl : DeviceControl
    {
        public SwitchControl()
        {
            icon.Source = StaticVars.switchISource;
            short interfaceNumber = 0;
            foreach (NetworkInterface it in interfaces)
            {
                it.Adress = new MacAdress("00:00:00:03:" + Simulation.SwitchCounter.ToString("X2") + ":" + interfaceNumber.ToString("X2"));
                interfaceNumber++;
            }
            deviceLabel.Content = "SWITCH " + Simulation.SwitchCounter;
            using (var stream = new MemoryStream())
            {
                var encoder = new PngBitmapEncoder { Interlace = PngInterlaceOption.On };
                if (icon.Source != null) encoder.Frames.Add(BitmapFrame.Create((BitmapSource)icon.Source));
                encoder.Save(stream);
                RawImageData = stream.ToArray();
            }
            Simulation.SwitchCounter++;
        }
        private List<DelayTimer> timers = new List<DelayTimer>();

        public SwitchControl(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        internal override void stopReceiving(Signal signal, NetworkInterface networkInterface)
        {
            receivedData.Add(new ReceivedData(signal.ethernet, Simulation.tickCount, FrameAction.Switched));
        }

        internal override void abortReceiving(Signal signal, NetworkInterface networkInterface)
        {
            foreach (NetworkInterface it in interfaces)
                it.abortEthernetFrame(signal.ethernet);
        }

        internal override void startReceiving(Signal signal, NetworkInterface networkInterface)
        {
            DelayTimer switchingDelay = new DelayTimer(25000.0*(1.0/(double)networkInterface.wireEnd.getConnectionType()), networkInterface, signal);
            switchingDelay.Start();
            switchingDelay.Tick+=switchingDelay_Tick;
            timers.Add(switchingDelay);
            
        }

        void switchingDelay_Tick(object sender, EventArgs e)
        {
            NetworkInterface networkInterface = ((DelayTimer)sender).networkInterface;
            Signal signal = ((DelayTimer)sender).signal;
            ((DelayTimer)sender).Stop();
            timers.Remove((DelayTimer)sender);
            switchTable.addMAC(networkInterface, signal.ethernet.source);


            NetworkInterface senderInterface = switchTable.findInterface(signal.ethernet.destination);
            if (senderInterface != null && senderInterface.wireEnd != null)
            {
                senderInterface.sendFrame(signal.ethernet);
            }
            else
            {
                foreach (NetworkInterface it in interfaces)
                {
                    if (it.wireEnd != null && it != networkInterface)
                    {
                        it.sendFrame(signal.ethernet);
                    }
                }
            }
        }

        public override void sendFrame(Ethernet frameData)
        {
            NetworkInterface senderInterface = switchTable.findInterface(frameData.destination);
            if (senderInterface != null && senderInterface.wireEnd != null)
            {
                frameData.source = senderInterface.Adress;
                senderInterface.sendFrame(frameData);
            }
            else
            {
                foreach (NetworkInterface it in interfaces)
                {
                    if (it.wireEnd != null)
                    {
                        it.sendFrame(frameData);
                    }
                }
            }
        }
        protected override void DeviceControlContextMenuPropertiesClick(object sender, RoutedEventArgs e)
        {
            (new SwitchSettings(this)).ShowDialog();
        }
        internal override void reset()
        {
            foreach (DelayTimer it in timers)
            {
                it.Stop();
            }
            timers.Clear();
        }
    }
}